<?php
/*-------------------------------------------------------------------------\
|
|  ========================================================
|  Fusion Registry GPL
|  Copyright (C) 2007 Fusion Scripts
|
|  This program is free software; you can redistribute it and/or
|  modify it under the terms of the GNU General Public License
|  as published by the Free Software Foundation; either version 2
|  of the License, or (at your option) any later version.
|
|  This program is distributed in the hope that it will be useful,
|  but WITHOUT ANY WARRANTY; without even the implied warranty of
|  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
|  GNU General Public License for more details.
|
|  You should have received a copy of the GNU General Public License
|  along with this program; if not, write to the Free Software
|  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
|  ========================================================
|
|  Email: info@fusionscripts.com
|  Web-Site: http://www.fusionscripts.com/
|
|  $Id: ad_tools.php 4 2008-08-03 01:43:03Z registry.fusion $
|
\-------------------------------------------------------------------------*/

/**
 * This is the admin interface for tools of the Fusion Registry
 *
 * @package Fusion Registry
 * @subpackage admin
 * @version $Id: ad_tools.php 4 2008-08-03 01:43:03Z registry.fusion $
 */

if ( ! defined( 'AD_REGISTRY_CALLED' ) )
{
    print "<h1>Incorrect access</h1>You cannot access this file directly.";
    exit();
}

/**#@+
 * Fusion Registry requires
 */
require_once( AD_REGISTRY_PATH.'ad_registry_loader.php' );
require_once( KERNEL_PATH.'class_image.php' );
/**#@-*/

/**
 * Class ad_registry_tools houses tools to keep the Fusion Registry running smoothly
 *
 * @package Fusion Registry
 * @subpackage admin
 */
class ad_registry_tools
{
    /**#@+ @var object */
    var $ipsclass;
    var $ad_registry_loader;
    var $ad_registry_verify;
    /**#@-*/

    /** @var resource */
    var $log_handle;

    /**
     * Intialization of ad_registry_tools
     *
     * Another traffic cop function, there should be minimal procedural code
     * here. When we initialize the {@link ad_registry_loader} class the license
     * will be validated.
     */
    function auto_run()
    {
        // Kill globals
        $tmp_in = array_merge( $_GET, $_POST, $_COOKIE );

        foreach ( $tmp_in as $k => $v )
        {
            unset($$k);
        }

        // Initialize ad_registry_loader
        $this->ad_registry_loader = new ad_registry_loader();
        $this->ad_registry_loader->ipsclass =& $this->ipsclass;
        $this->ad_registry_loader->auto_run(&$this);

        switch($this->ipsclass->input['code'])
        {
            case 'rebuild_thumbs':
                $this->rebuild_thumbs();
                break;

            case 'orphan_search':
                $this->orphan_search();
                break;

            case 'orphan_remove':
                $this->orphan_remove();
                break;

            default:
                $this->main_menu();
                break;
        }
    }


    /**
     * Find those Orphans!
     *
     * Basic chain of events are to compare all the known file names
     * that are stored in the database against what is actually on the
     * file system. If files are found on the file system that are not
     * registered in the database, it is considered an orphan. This
     * function does not act upon the orphans, it only reports it's
     * findings back to the end user.
     */
    function orphan_search()
    {
        $active_attach = array();
        $present_attach = array();
        $orphan_attach = array();

        // First let's compile a list of all the attachments that are currently
        //   tracked in the database (currently in use)
        $this->ipsclass->DB->simple_construct( array( 'select' => '*', 'from' => 'registry_images', 'order' => 'attach_id ASC' ) );
        $attach_result = $this->ipsclass->DB->simple_exec();

        while ( $row = $this->ipsclass->DB->fetch_row($attach_result) )
        {
            // Since remote images aren't on our local drive we won't track them ;)
            if ( !preg_match("/^http:\/\//i", $row['attach_location']) )
            {
                $active_attach[] = $row['attach_location'];
            }

            if ( !preg_match("/^http:\/\//i", $row['attach_thumb_location']) )
            {
                $active_attach[] = $row['attach_thumb_location'];
            }
        }

        // Now let's grab the list of currently present attachments on
        //   the local drive
        $upload_dir = opendir($this->ipsclass->vars['upload_dir']);

        while ( false !== ( $file = readdir($upload_dir) ) )
        {
            if ( preg_match("/^registry/", $file) OR in_array($file,$active_attach) )
            {
                $present_attach[] = $file;
            }
        }

        closedir($upload_dir);

        // Calculate which ones don't belong
        $orphan_attach = array_diff($present_attach, $active_attach);

        //-------------------------------
        // Construct menu HTML
        //-------------------------------

        $this->ipsclass->html .= $this->ipsclass->skin_acp_global->information_box( "Fusion Registry Orphan Locator", "Below are all the orphaned files that were found.  An orphaned file is defined as a file that exists on your local drive that is no longer present in the database.<br />Please check all the applicable orphans you wish to delete.<br /><br />". $this->ad_registry_loader->imgs['warning'] ."&nbsp;<b>This operation is not undo-able!  Once you choose to remove an orphan it is gone for good.</b>".'<br />&nbsp;' ) . "<br >";

        // Inject our javascript toggle
        $this->ipsclass->html .= <<<EOF
<SCRIPT LANGUAGE="JavaScript">
<!--
function select_all() {
    for (var i=0;i<document.theAdminForm.elements.length;i++)
    {
       var e = document.theAdminForm.elements[i];
       if (e.type=='checkbox')
       {
          if (e.checked == false) {
               e.checked = true;
          }
          else
               e.checked = false;
          }
     }
     return 1;
}
-->
</script>
EOF;

        $this->ipsclass->html .= $this->ipsclass->adskin->start_form( array( 1 => array( 'code', 'orphan_remove' ),
                                                                             2 => array( 'act' , REGISTRY_URL    ),
                                                                             3 => array( 'menu', 'tools'         ),
                                                                             4 => array( 'section', 'components' ),
                                                                    )      );

        $this->ipsclass->html .= $this->ipsclass->adskin->start_table( "Select Orphaned Files to Remove -- <a href='#' onClick='select_all();return false;'><i>(Click to toggle all checkboxes below)</i></a>" );

        // If they don't have any, let them know
        if ( count($orphan_attach) <= 0 )
        {
            $this->ipsclass->html .= $this->ipsclass->adskin->add_td_row( array( "Congratulations! You have no orphaned files!" ) );
        }
        else
        {
            // Otherwise print them all out baby!
            foreach ($orphan_attach as $orphan_file)
            {
                $this->ipsclass->html .= $this->ipsclass->adskin->add_td_row( array( $this->ipsclass->adskin->form_checkbox( "orphan_attach[$orphan_file]", 0, 1 ) . "&nbsp;<a href='" .$this->ipsclass->vars['upload_url']. "/$orphan_file' target='_blank'>$orphan_file</a>" ) );
            }
        }

        $this->ipsclass->html .= $this->ipsclass->adskin->end_form('Remove Selected Orphans');

        $this->ipsclass->html .= $this->ipsclass->adskin->end_table();

        $this->ipsclass->admin->output();
    }


    /**
     * Remove orphaned files!
     *
     * @todo Implement a backup routine so there is something to fall back on if this fuction does bad things
     */
    function orphan_remove()
    {
        $output = array();

        // If they didn't select anything we won't get an array here ;)
        if ( is_array($this->ipsclass->input['orphan_attach']) )
        {
            // Loop through the selected list from the user
            while ( list($orphan_file, ) = each ($this->ipsclass->input['orphan_attach']) )
            {
                // Just to make sure, if the file exists...
                if ( @file_exists( $this->ipsclass->vars['upload_dir'] .'/'. $orphan_file ) )
                {
                    // Remove it
                    @unlink( $this->ipsclass->vars['upload_dir'] .'/'. $orphan_file );

                    // And report what we just did
                    $output[] = 'Removed: '.$orphan_file;
                }
            }

            // Report our mischief ways :)
            $text = "<b>Orphaned Files Removed</b><br /><br />".implode( "<br />", $output );
            $url = "act=".REGISTRY_URL."&section=components&menu=tools";
            $time = 5;

            // Big brother is watching :)
            $this->ipsclass->admin->save_log("Removed Orphaned Fusion Registry Files");
        }
        else
        {
            $text = "<b>No orphaned files were selected, therefore none were removed ;)</b>";
            $url = "act=".REGISTRY_URL."&section=components&menu=tools";
            $time = 5;
        }

        // End of the show, c'ya
        $this->ipsclass->admin->redirect( $url, $text, 0, $time );
    }


    /**
     * Rebuild All Thumbnails
     *
     * If the end user opted to create a log we will use function {@link _log}
     * to maintain an ongoing log during the cycled execution of this function.
     *
     * @uses ad_registry_tools::remote_file_exists Verify remote file exists so we don't bomb out PHP
     * @todo Implement a backup routine so there is something to fall back on if this fuction does bad things
     */
    function rebuild_thumbs()
    {
        // Set up
        $done       = 0;
        $start      = intval( $this->ipsclass->input['st'] );
        $end        = intval( $this->ipsclass->input['pergo'] ) ? intval( $this->ipsclass->input['pergo'] ) : 20;
        $end        += $start;
        $output     = array();
        $log_file   = $this->ipsclass->vars['upload_dir'] .'/'. $this->ipsclass->input['log_file'];

        // Decode any html entities in our convert options/path
        $convert_options = function_exists('html_entity_decode')
                         ? html_entity_decode($this->registry_config['convert_options'])
                         : $this->unhtmlentities($this->registry_config['convert_options']);

        $convert_path = function_exists('html_entity_decode')
                      ? html_entity_decode($this->registry_config['convert_path'])
                      : $this->unhtmlentities($this->registry_config['convert_path']);

        // Are we logging?
        if ( empty($log_file) == FALSE )
        {
            // If we are just starting make sure we start with a clean file
            if ( $start == 0 )
            {
                $log_type = 'wb';
            }
            // If not then append to existing log
            else
            {
                $log_type = 'ab';
            }

            // Open that log up!
            $this->log_handle = @fopen( $log_file, $log_type );
        }

        // Got any more?
        $tmp = $this->ipsclass->DB->simple_exec_query( array( 'select' => '*', 'from' => 'registry_images', 'where' => "attach_is_image='1' and attach_id > $end" ) );
        $max = intval( $tmp['attach_id'] );

        // Only do the dirty work if we are using ImageMagick!
        if ( ($this->registry_config['thumbnail_type'] == 'imagemagick') AND
             (@file_exists(preg_replace("/\"/", "",$this->registry_config['convert_path']))) )
        {
            // Loop through the images avoiding limit
            $this->ipsclass->DB->simple_construct( array( 'select' => '*', 'from' => 'registry_images', 'where' => "attach_is_image='1' and attach_id >= $start and attach_id < $end", 'order' => 'attach_id ASC' ) );
            $image_result = $this->ipsclass->DB->simple_exec();

            while ( $image_row = $this->ipsclass->DB->fetch_row($image_result) )
            {
                // Logging
                $this->_log('Processing attach_id: '. $image_row['attach_id']);

                // The process is a little different for local vs. remote files
                if ( preg_match("/^http:\/\//i", $image_row['attach_location']) )
                {
                    // This is a remote image!
                    $file_name = preg_replace( "/^(.+?)\..+?$/", "\\1", $image_row['attach_file'] );

                    // Generate our temp file name
                    $tmp_file_name = $file_name . time() .'.'. $image_row['attach_ext'];

                    // Generate our thumb file name
                    if ( (empty($image_row['attach_thumb_location'])) OR ($image_row['attach_thumb_location'] == "remote") )
                    {
                        // We are going to use the attach_file name to create our _thumb
                        //   file name since this image did not have a thumb before.
                        $thumb_file_name = $file_name . time() . '_thumb.' . $image_row['attach_ext'];
                    }
                    else
                    {
                        // We already know the thumbnail filename :)
                        $thumb_file_name = $image_row['attach_thumb_location'];
                    }

                    $this->_log('Remote image: '. $image_row['attach_location'], 1);
                    $this->_log('file_name: '. $file_name, 2);
                    $this->_log('tmp_file_name: '. $tmp_file_name, 2);

                    // Make sure it exists, or we'll get nasty errors!
                    if ( $this->remote_file_exists($image_row['attach_location']) )
                    {
                        // Download the remote image to our temporary file
                        $infile = @fopen ($image_row['attach_location'], "rb");
                        $outfile = @fopen ($this->ipsclass->vars['upload_dir']."/".$tmp_file_name, "wb");

                        // Set our custom timeout
                        if ( function_exists('stream_set_timeout') )
                        {
                            @stream_set_timeout($infile, $this->registry_config['remote_timeout']);
                        }

                        while (!@feof ($infile))
                        {
                            @fwrite($outfile, @fread ($infile, 4096));
                        }
                        @fclose($outfile);
                        @fclose($infile);

                        // ImageMagick's source/dest filenames
                        $source = $this->ipsclass->vars['upload_dir']."/".$tmp_file_name;
                        $dest = $this->ipsclass->vars['upload_dir']."/".$thumb_file_name;

                        // We are using escapeshellcmd to prevent naughty use
                        $cmd = escapeshellcmd($convert_path .' '. $convert_options .' -scale '. $this->registry_config['thumbnail_resolution'] .'x'. $this->registry_config['thumbnail_resolution'] ." $source $dest");

                        // Create our pretty thumb
                        exec($cmd, $result);

                        // Chmod it, because, because... I feel like it, lol
                        @chmod( $dest, 0777 );

                        // Remove our temporary file!
                        @unlink( $source );

                        // Grab the width/height of the thumb
                        $img_size = @GetImageSize( $dest );

                        if ( $img_size[0] > 0 and $img_size[1] > 0 )
                        {
                            $thumb_width = $img_size[0];
                            $thumb_height = $img_size[1];
                        }
                        else
                        {
                            // Something went wrong with GetImageSize :(
                            $thumb_width = 0;
                            $thumb_height = 0;
                        }

                        // Update the DB
                        $db_string = $this->ipsclass->DB->compile_db_update_string( array( 'attach_thumb_location' => $thumb_file_name,
                                                                                           'attach_thumb_width' => $thumb_width,
                                                                                           'attach_thumb_height' => $thumb_height
                                                                                  )      );

                        $this->ipsclass->DB->query("UPDATE ibf_registry_images SET $db_string WHERE attach_id = '". $image_row['attach_id'] ."'");

                        // Add the status message
                        $output[] = "Rebuilt: ".$image_row['attach_location'].' -> '.$thumb_file_name;

                        $this->_log('Thumb file: '.$thumb_file_name,1);
                    }
                    else
                    {
                        // Tell them that the remote file doesn't exists
                        $output[] = "<b><font color='red'>ERROR</font></b> -- Remote file does not exist! (".$image_row['attach_file'].")";

                        $this->_log('ERROR -- Remote file does not exist!',1);
                    }
                }
                else
                {
                    // This is a local image

                    // ImageMagick's source filename
                    $source = $this->ipsclass->vars['upload_dir']."/".$image_row['attach_location'];

                    $this->_log('Source file: '.$image_row['attach_location'], 1);

                    // Generate our thumb file name
                    if ( empty($image_row['attach_thumb_location']) )
                    {
                        // We are going to use the attach_id to create our _thumb
                        //   file name since this image did not have a thumb before.
                        $thumb_file_name = preg_replace( "/^(.+?)\..+?$/", "\\1", $image_row['attach_location'] );

                        $thumb_file_name .= '_thumb' .'.'. $image_row['attach_ext'];
                    }
                    else
                    {
                        // We already know the thumbnail filename :)
                        $thumb_file_name = $image_row['attach_thumb_location'];
                    }

                    // ImageMagick's source filename
                    $dest = $this->ipsclass->vars['upload_dir']."/".$thumb_file_name;

                    // We are using escapeshellcmd to prevent naughty use
                    $cmd = escapeshellcmd($convert_path .' '. $convert_options .' -scale '. $this->registry_config['thumbnail_resolution'] .'x'. $this->registry_config['thumbnail_resolution'] ." $source $dest");

                    // Create our pretty thumb
                    exec($cmd, $result);

                    // Chmod it, because, because... I feel like it, lol
                    @chmod( $dest, 0777 );

                    // Grab the width/height of the thumb
                    $img_size = @GetImageSize( $dest );

                    if ( $img_size[0] > 0 and $img_size[1] > 0 )
                    {
                        $thumb_width = $img_size[0];
                        $thumb_height = $img_size[1];
                    }
                    else
                    {
                        // Something went wrong with GetImageSize :(
                        $thumb_width = 0;
                        $thumb_height = 0;
                    }

                    // Update the DB
                    $db_string = $this->ipsclass->DB->compile_db_update_string( array( 'attach_thumb_location' => $thumb_file_name,
                                                                                       'attach_thumb_width' => $thumb_width,
                                                                                       'attach_thumb_height' => $thumb_height
                                                                              )      );

                    $this->ipsclass->DB->query("UPDATE ibf_registry_images SET $db_string WHERE attach_id = '". $image_row['attach_id'] ."'");

                    // Add the status message
                    $output[] = "Rebuilt: ".$image_row['attach_location'].' -> '.$thumb_file_name;

                    $this->_log('Thumb file: '.$thumb_file_name, 1);

                } // End if remote/local

                $done++;

            } // End while loop

            // Big brother is watching :)
            $this->ipsclass->admin->save_log("Rebuilt All Fusion Registry Thumbnails");
        }
        elseif ( $this->registry_config['thumbnail_type'] == 'gd' )
        {
            // Loop through the images avoiding limit
            $this->ipsclass->DB->simple_construct( array( 'select' => '*', 'from' => 'registry_images', 'where' => "attach_is_image='1' and attach_id >= $start and attach_id < $end", 'order' => 'attach_id ASC' ) );
            $image_result = $this->ipsclass->DB->simple_exec();

            while ( $image_row = $this->ipsclass->DB->fetch_row($image_result) )
            {
                $this->_log('Processing attach_id: '. $image_row['attach_id']);

                // Create our new image object
                $image = new class_image();
                $return = array();

                // If it is a remote image, don't place the ./uploads/ path into our object
                if ( preg_match( "/^http:\/\/$/i", $image_row['attach_location'] ) )
                {
                    $in_file_dir = '';
                }
                else
                {
                    $in_file_dir = $this->ipsclass->vars['upload_dir'];
                }

                $image->in_type        = 'file';
                $image->out_type       = 'file';
                $image->in_file_dir    = $in_file_dir;
                $image->in_file_name   = $image_row['attach_location'];
                $image->desired_width  = $this->registry_config['thumbnail_resolution'];
                $image->desired_height = $this->registry_config['thumbnail_resolution'];
                $image->gd_version     = $this->ipsclass->vars['gd_version'];

                // The process is a little different for local vs. remote files
                if ( preg_match("/^http:\/\//i", $image_row['attach_location']) )
                {
                    // This is a remote image!
                    $file_name = preg_replace( "/^(.+?)\..+?$/", "\\1", $image_row['attach_file'] );

                    // Generate our temp file name
                    $tmp_file_name = $file_name .'-'. time() .'.'. $image_row['attach_ext'];

                    $this->_log('Remote image: '. $image_row['attach_location'], 1);
                    $this->_log('file_name: '. $file_name, 2);
                    $this->_log('tmp_file_name: '. $tmp_file_name, 2);

                    // Make sure it exists, or we'll get nasty errors!
                    if ( $this->remote_file_exists($image_row['attach_location']) )
                    {
                        // Download the remote image to our temporary file
                        $infile = @fopen ($image_row['attach_location'], "rb");
                        $outfile = @fopen ($this->ipsclass->vars['upload_dir']."/".$tmp_file_name, "wb");

                        // Set our custom timeout
                        if ( function_exists('stream_set_timeout') )
                        {
                            @stream_set_timeout($infile, $this->registry_config['remote_timeout']);
                        }

                        while (!@feof ($infile))
                        {
                            @fwrite($outfile, @fread ($infile, 4096));
                        }
                        @fclose($outfile);
                        @fclose($infile);

                        // source filename
                        $source = $this->ipsclass->vars['upload_dir']."/".$tmp_file_name;

                        $image->in_file_dir = $this->ipsclass->vars['upload_dir'];
                        $image->in_file_name = $tmp_file_name;

                        // Create our pretty thumb
                        $return = $image->generate_thumbnail();

                        // Remove our temporary file, if it isn't still being used!
                        if ( $image->in_file_name != $return['thumb_location'] )
                        {
                            @unlink( $source );
                        }

                        // If we had an old thumbnail, delete it, carefully!
                        if ( (!empty($image_row['attach_thumb_location'])) AND
                             ($image_row['attach_thumb_location'] != "remote") AND
                             ($image_row['attach_thumb_location'] != $return['thumb_location']) AND
                             ($image_row['attach_location'] != $return['thumb_location']) )
                        {
                            if ( @file_exists($this->ipsclass->vars['upload_dir']."/".$image_row['attach_thumb_location']) )
                            {
                                @unlink($this->ipsclass->vars['upload_dir']."/".$image_row['attach_thumb_location']);
                            }
                        }

                        // Were we successful in creating the thumb? If not don't fool ourselves :(
                        if ( !@file_exists($this->ipsclass->vars['upload_dir']."/".$return['thumb_location']) OR
                           ( empty($return['thumb_location']) == TRUE ) )
                        {
                            // Since something went wrong let's make sure we don't create broken images
                            $return['thumb_location'] = 'remote';
                            $return['thumb_height'] = 0;
                            $return['thumb_width'] = 0;
                        }

                        // Update the DB
                        $db_string = $this->ipsclass->DB->compile_db_update_string( array( 'attach_thumb_location' => $return['thumb_location'],
                                                                                           'attach_thumb_width' => $return['thumb_height'],
                                                                                           'attach_thumb_height' => $return['thumb_length']
                                                                                  )      );

                        $this->ipsclass->DB->query("UPDATE ibf_registry_images SET $db_string WHERE attach_id = '". $image_row['attach_id'] ."'");

                        // Add the status message
                        $output[] = "Rebuilt: ".$image_row['attach_location'].' -> '.$return['thumb_location'];

                        $this->_log('Thumb file: '.$return['thumb_location'],1);
                    }
                    else
                    {
                        // Tell them that the remote file doesn't exists
                        $output[] = "<b><font color='red'>ERROR</font></b> -- Remote file does not exist! (".$image_row['attach_file'].")";

                        $this->_log('ERROR -- Remote file does not exist!',1);
                    }
                }
                else
                {
                    // This is a local image

                    // Source filename
                    $source = $this->ipsclass->vars['upload_dir']."/".$image_row['attach_location'];

                    $image->in_file_dir = $this->ipsclass->vars['upload_dir'];
                    $image->in_file_name = $image_row['attach_location'];

                    $this->_log('Source file: '.$image_row['attach_location'], 1);

                    // Create our pretty thumb
                    $return = $image->generate_thumbnail();

                    // If we created a new thumb file, delete the old one if we had one
                    // Okay that sounded confusing, lol
                    if ( ($return['thumb_location'] != $image_row['attach_thumb_location']) AND
                         @file_exists( $this->ipsclass->vars['upload_dir'] .'/'. $image_row['attach_thumb_location'] ) AND
                         (empty($image_row['attach_thumb_location']) == FALSE) AND
                         ($image_row['attach_location'] != $return['thumb_location']) )
                    {
                        // Remove the old thumb that is no longer used
                        @unlink( $this->ipsclass->vars['upload_dir'] .'/'. $image_row['attach_thumb_location'] );
                    }

                    // Were we successful in creating the thumb? If not don't fool ourselves :(
                    if ( !@file_exists($this->ipsclass->vars['upload_dir']."/".$return['thumb_location']) OR
                       ( empty($return['thumb_location']) == TRUE ) )
                    {
                        // Since something went wrong let's make sure we don't create broken images
                        $return['thumb_location'] = $image_row['attach_location'];
                        $return['thumb_height'] = 0;
                        $return['thumb_width'] = 0;
                    }

                    // Update the DB
                    $db_string = $this->ipsclass->DB->compile_db_update_string( array( 'attach_thumb_location' => $return['thumb_location'],
                                                                                       'attach_thumb_width' => $return['thumb_height'],
                                                                                       'attach_thumb_height' => $return['thumb_length']
                                                                              )      );

                    $this->ipsclass->DB->query("UPDATE ibf_registry_images SET $db_string WHERE attach_id = '". $image_row['attach_id'] ."'");

                    // Add the status message
                    $output[] = "Rebuilt: ".$image_row['attach_location'].' -> '.$return['thumb_location'];

                    $this->_log('Thumb file: '.$return['thumb_location'], 1);

                } // End if remote/local

                $done++;

            } // End while loop
        }
        else
        {
            // We won't run this tool without ImageMagick or GD!
            $output[] = "<b>ERROR !</b> The ImageMagick binary 'convert' can not be found at the configured location (".$convert_path.")!";
        }

        // Finished or more?
        if ( ! $done and ! $max )
        {
            // Yup, we're done
            $text = "<b>Rebuild All Thumbnails completed</b><br />".implode( "<br />", $output );
            $url  = "act=".REGISTRY_URL."&section=components&menu=tools";
            $time = 2;

            // Big brother is watching :)
            $this->ipsclass->admin->save_log("Rebuilt All Fusion Registry Thumbnails");
        }
        else
        {
            // Keep going!
            $text = "<b>Up to $end processed so far, continuing...</b><br />".implode( "<br />", $output );
            $url  = "act=".REGISTRY_URL."&section=components&menu=tools&amp;code=".$this->ipsclass->input['code'].'&amp;pergo='.$this->ipsclass->input['pergo'].'&amp;st='.$end.'&amp;log_file='.$this->ipsclass->input['log_file'];
            $time = 0;
        }

        // End of the show, c'ya
        $this->ipsclass->admin->redirect( $url, $text, 0, $time );
    }


    /**
     * Display HTML for Fusion Registry tools menu
     */
    function main_menu()
    {
        $this->ipsclass->html .= $this->ipsclass->skin_acp_global->information_box( "Fusion Registry Tools", "Below are tools that can help you keep your Fusion Registry running smooth.".'<br />&nbsp;' ) . "<br >";

        //-------------------------------
        // Rebuild Thumbs
        //-------------------------------

        $this->ipsclass->html .= $this->ipsclass->adskin->start_form( array( 1 => array( 'code', 'rebuild_thumbs' ),
                                                                             2 => array( 'act' , REGISTRY_URL     ),
                                                                             3 => array( 'menu', 'tools'          ),
                                                                             4 => array( 'section', 'components'  ),
                                                                    )      );

        $this->ipsclass->adskin->td_header[] = array( "&nbsp;"    , "40%" );
        $this->ipsclass->adskin->td_header[] = array( "&nbsp;"    , "60%" );

        $this->ipsclass->html .= $this->ipsclass->adskin->start_table( "Rebuild All Thumbnails" );

        $this->ipsclass->html .= $this->ipsclass->adskin->add_td_row( array( "<b>Rebuild All Thumbnails</b><div style='color:gray'>If you have recently changed the 'Create Thumbnails Using?' option, the thumbnail resolution, or have broken thumbnail images use this tool to rebuild all thumbnails. Depending on the size of your registry this tool can take a few minutes to run and is CPU intensive!</div>",
                                                                             $this->ipsclass->adskin->form_simple_input( 'pergo', '20', 5 ). "&nbsp;Per Cycle"
                                                                    )      );

        $this->ipsclass->html .= $this->ipsclass->adskin->add_td_row( array( "<b>Create Detailed Log?</b><div style='color:gray'>If you have would like the Fusion Registry to create a detailed log of the rebuild actions please enter a filename here.<br /><br />Note that any existing file with the same name will be overwritten!<br /><br />If you do not want a detailed log to be created leave this field blank.</div>",
                                                                             $this->ipsclass->vars['upload_dir'] .'/&nbsp;'. $this->ipsclass->adskin->form_simple_input( 'log_file','',20 )
                                                                    )      );

        $this->ipsclass->html .= $this->ipsclass->adskin->end_form('Rebuild All Thumbnails');

        $this->ipsclass->html .= $this->ipsclass->adskin->end_table();

        $this->ipsclass->html .= '<br />';

        //-------------------------------
        // Find/Remove Orphans
        //-------------------------------

        $this->ipsclass->html .= $this->ipsclass->adskin->start_form( array( 1 => array( 'code', 'orphan_search' ),
                                                                             2 => array( 'act' , REGISTRY_URL    ),
                                                                             3 => array( 'menu', 'tools'         ),
                                                                             4 => array( 'section', 'components' ),
                                                                    )      );

        $desc = 'The Find/Remove Orphans tool is used to locate any abondanded files that the Fusion Registry had once created.  These abandoned files could be a result of doing any manual work in the database, running the rebuild tool and it failing part way through, or after substantial upgrading to the Fusion Registry.  Under normal circumstances there should be no orphaned files.<br /><br />The first step of this tool is just to search for files, no action will be taken unless you confirm the findings on the next step.';

        $this->ipsclass->html .= $this->ipsclass->adskin->start_table( "Find/Remove Orphans", $desc );

        $this->ipsclass->html .= $this->ipsclass->adskin->end_form('Search for Orphans');

        $this->ipsclass->html .= $this->ipsclass->adskin->end_table();

        // That's all folk!
        $this->ipsclass->admin->output();
    }


    /**
     * Verify a remote file exists
     *
     * This is kind of tricky, this verifies against the response code
     * from trying to get to the remote file. Basically if we don't
     * response code 200 we will assume something is wrong and return
     * false. This code does take into account redirect responses and
     * will follow the redirect to verify that location.
     *
     * @param string $url Remote file to verify
     * @return boolean TRUE|FALSE
     */
    function remote_file_exists($url)
    {
        // Make sure php will allow us to do this...
        if ( ini_get('allow_url_fopen') )
        {
            $url_p = parse_url($url);

            if ( isset($url_p['host']) )
            {
                $host = $url_p['host'];
            }
            else
            {
               return false;
            }

            $fp = @fsockopen ($host, 80, $errno, $errstr, 20);
            if (!$fp)
            {
               return false;
            }
            else
            {
               $parse = parse_url($url);
               $host = $parse['host'];

               @fputs($fp, 'HEAD '.$url." HTTP/1.1\r\n");
               @fputs($fp, 'HOST: '.$host."\r\n");
               @fputs($fp, "Connection: close\r\n\r\n");
               $headers = '';
               while (!@feof ($fp))
               {
                   $headers .= @fgets ($fp, 128);
               }
            }
            @fclose ($fp);

            $arr_headers = explode("\n", $headers);

            if ( isset($arr_headers[0]) )
            {
               if ( strpos($arr_headers[0], '200') !== false )
               {
                   return true;
               }

               if ( ( strpos($arr_headers[0], '404') !== false ) ||
                    ( strpos($arr_headers[0], '509') !== false ) ||
                    ( strpos($arr_headers[0], '410') !== false ) )
               {
                   return false;
               }

               if ( (strpos($arr_headers[0], '301') !== false ) ||
                    (strpos($arr_headers[0], '302') !== false ) )
               {
                   preg_match("/Location:\s*(.+)\r/i", $headers, $matches);

                   if ( !isset($matches[1]) )
                   {
                       return false;
                   }

                   $nextloc = $matches[1];

                   return $this->remote_file_exists($nextloc);
               }
            }

            // If we are still here then we got an unexpected header
            return false;
        }
        else
        {
            // Since we aren't allowed to use URL's bomb out
            return false;
        }
    }


    /**
     * Used for detailed logging during thumbnail rebuilding
     *
     * @param string $message Text to log
     * @param integer $level Amount of tab characters to preceed line with
     * @return boolean TRUE
     */
    function _log ($message,$level=0)
    {
        if ( empty($this->log_handle) == FALSE )
        {
            // Make sure we end with a new line
            if ( !preg_match('/^.+?\n$/', $message) )
            {
                $message .= "\n";
            }

            // Prepend number of tabs equal to level
            while ( $level > 0 )
            {
                $message = "\t".$message;
                $level--;
            }

            // Write the message to the log
            @fwrite( $this->log_handle, $message );
        }

        return TRUE;
    }


    /**
     * For users prior to PHP 4.3.0 that do not have the function html_entity_decode
     */
    function unhtmlentities($string)
    {
        // replace numeric entities
        $string = preg_replace('~&#x([0-9a-f]+);~ei', 'chr(hexdec("\\1"))', $string);
        $string = preg_replace('~&#([0-9]+);~e', 'chr(\\1)', $string);
        // replace literal entities
        $trans_tbl = get_html_translation_table(HTML_ENTITIES);
        $trans_tbl = array_flip($trans_tbl);
        return strtr($string, $trans_tbl);
    }
}
?>